#include "actionfileparser.h"

#include <QDebug>
#include <QFile>
#include <QTextStream>
#include <actionfilewriter.h>

ActionFileParser::ActionFileParser()
{
}


int ActionFileParser::getDuration(QString filename){
    int curTimestamp;
    QString curLine, prevLine;
    QTextStream inStream, lineStream;

    //Open the file
    QFile file(filename);

    if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
        return NULL;
    inStream.setDevice(&file);

    curLine = inStream.readLine();
    while(!curLine.isEmpty()){
        prevLine = curLine;
        curLine = inStream.readLine();
    }
    //The last line should contain the last timestamp
    lineStream.setString(&prevLine);
    lineStream >> curTimestamp;
    //This timestamp is the duration
    file.close();
    return curTimestamp;
}


RobotAction* ActionFileParser::parse(QString filename, Robot* robot){
    RobotAction* newAction;
    int i, curJointID, curTimestamp;
    qint64 jointPositionsBeginning;
    float curJointPosition;
    bool isFloat;
    char curChar;
    QString curLine, prevLine, curField, curSoundFile;
    QList<int> jointIDs;
    QTextStream inStream, lineStream;

    //Open the file
    QFile file(filename);

    if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
        return NULL;
    inStream.setDevice(&file);

    //The first line contains the name of the action
    curLine = inStream.readLine().trimmed();
    newAction = new RobotAction(robot, curLine);

    //The second line contains joint ID information
    curLine = inStream.readLine().trimmed();
    lineStream.setString(&curLine);
    //Throw away the "timestamp" field
    lineStream >> curField;
    //Read all of the jointIDs and store them in a list
    do{
        lineStream >> curJointID;
        jointIDs.append(curJointID);
    }while(!lineStream.atEnd());

    //In order for the action to be created correctly,
    //we need to know the duration of the motion before
    //we begin to set the key values. (The action uses "steps"
    //instead of msec)
    jointPositionsBeginning = inStream.pos();
    curLine = inStream.readLine().trimmed();
    while(!curLine.isNull()){
        if (!curLine.isEmpty() && curLine.at(0) != '#') {
            prevLine = curLine;
        }
        curLine = inStream.readLine().trimmed();
    }
    //The last line should contain the last timestamp
    lineStream.setString(&prevLine);
    lineStream >> curTimestamp;
    //This timestamp is the duration
    qDebug() << "setting motion duration to: " << curTimestamp;
    newAction->setMotionDuration(curTimestamp);

    //Reset the stream to the beginning of the joint position information
    inStream.seek(jointPositionsBeginning);

    //Begin reading the action information
    curLine = inStream.readLine().trimmed();
    while(!curLine.isNull()){
        lineStream.setString(&curLine);

        if (!curLine.isEmpty() && curLine.at(0) != '#') {
            //The first field is the timestamp
            lineStream >> curTimestamp;
            //The second field is either a joint position or "sound"
            lineStream >> curField;
            curJointPosition = curField.toFloat(&isFloat);

            if(isFloat){
                newAction->setKeyFrameAt(curTimestamp, jointIDs[0], curJointPosition);
                //The remaining fields are joint positions
                for(i = 1; i < jointIDs.length(); i++){
                    curJointID = jointIDs[i];
                    lineStream >> curJointPosition;

                    //Setting the keyframe will also appropriately update
                    //the action's duration
                    newAction->setKeyFrameAt(curTimestamp, curJointID, curJointPosition);
                }
            }
            else if(curField == "sound"){
                //We have a sound file
                curSoundFile.clear();
                lineStream.skipWhiteSpace();

                //Read character by character to capture whitespace in the file name
                while(!lineStream.atEnd()){
                    lineStream >> curChar;
                    curSoundFile.append(curChar);
                }

                //Add the sound to the action
                newAction->setSoundAt(curTimestamp, curSoundFile);
            }
        }

        curLine = inStream.readLine().trimmed();
    }

    file.close();

    return newAction;
}
